package cz.possoft.serializable.clovece.test;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import junit.framework.TestCase;
import cz.possoft.generic.utils.GenericUtils;
import cz.possoft.serializable.clovece.game.CloveceField;
import cz.possoft.serializable.clovece.game.CloveceGame;
import cz.possoft.serializable.clovece.game.ClovecePole;

/**
 * @author <a href="mailto:mposolda@gmail.com">Marek Posolda</a>
 */
public class CloveceTestCase extends TestCase 
{
   private CloveceGame game;
   
   @Override
   public void setUp()
   {
      game = new CloveceGame();
   }
   
   public void testCorrectStateOfPoleAfterCreatingGame()
   {
      System.out.println("testCorrectStateOfPoleAfterCreatingGame");
      game.setNoGame();
      
      ClovecePole clPole = game.getHraciPole();
      
      // assert field ID      
      assertEquals(clPole.getField(4), clPole.getFieldById(4));
      
      assertEquals(clPole.getStartField(0, GenericUtils.COLOR_WHITE), clPole.getFieldById(1000));
      assertEquals(clPole.getStartField(1, GenericUtils.COLOR_WHITE), clPole.getFieldById(1001));
      assertEquals(clPole.getStartField(2, GenericUtils.COLOR_WHITE), clPole.getFieldById(1002));
      assertEquals(clPole.getStartField(3, GenericUtils.COLOR_WHITE), clPole.getFieldById(1003));
      
      assertEquals(clPole.getStartField(0, GenericUtils.COLOR_BLACK), clPole.getFieldById(2000));
      assertEquals(clPole.getStartField(1, GenericUtils.COLOR_BLACK), clPole.getFieldById(2001));
      assertEquals(clPole.getStartField(2, GenericUtils.COLOR_BLACK), clPole.getFieldById(2002));
      assertEquals(clPole.getStartField(3, GenericUtils.COLOR_BLACK), clPole.getFieldById(2003));     
      
      assertEquals(clPole.getHomeField(0, GenericUtils.COLOR_WHITE), clPole.getFieldById(100));
      assertEquals(clPole.getHomeField(1, GenericUtils.COLOR_WHITE), clPole.getFieldById(101));
      assertEquals(clPole.getHomeField(2, GenericUtils.COLOR_WHITE), clPole.getFieldById(102));
      assertEquals(clPole.getHomeField(3, GenericUtils.COLOR_WHITE), clPole.getFieldById(103));
      
      assertEquals(clPole.getHomeField(0, GenericUtils.COLOR_BLACK), clPole.getFieldById(200));
      assertEquals(clPole.getHomeField(1, GenericUtils.COLOR_BLACK), clPole.getFieldById(201));
      assertEquals(clPole.getHomeField(2, GenericUtils.COLOR_BLACK), clPole.getFieldById(202));
      assertEquals(clPole.getHomeField(3, GenericUtils.COLOR_BLACK), clPole.getFieldById(203));  
      
      // test neighbors state
      CloveceField f0 = clPole.getField(0);
      CloveceField f1 = clPole.getField(1);
      CloveceField f2 = clPole.getField(2);      
      CloveceField f39 = clPole.getField(39);      
      
      CloveceField hw0 = clPole.getHomeField(0, GenericUtils.COLOR_WHITE);
      CloveceField hw3 = clPole.getHomeField(3, GenericUtils.COLOR_WHITE);
      
      CloveceField hb0 = clPole.getHomeField(0, GenericUtils.COLOR_BLACK);
      CloveceField hb3 = clPole.getHomeField(3, GenericUtils.COLOR_BLACK);
      
      assertEquals(f0.getNeigborFromDirection(), f1);
      assertTrue(f0.getNeighborsToDirection().size() == 1);
      assertTrue(f0.getNeighborsToDirection().contains(f39));
      
      assertEquals(f1.getNeigborFromDirection(), f2);
      assertTrue(f1.getNeighborsToDirection().size() == 2);
      assertTrue(f1.getNeighborsToDirection().contains(f0));      
      assertTrue(f1.getNeighborsToDirection().contains(hw0));
      
      assertEquals(hw3.getNeigborFromDirection(), clPole.getHomeField(2, GenericUtils.COLOR_WHITE));
      assertTrue(hw3.getNeighborsToDirection().size() == 0);
      
      assertEquals(hb3.getNeigborFromDirection(), clPole.getHomeField(2, GenericUtils.COLOR_BLACK));
      assertTrue(hb3.getNeighborsToDirection().size() == 0); 
      
      assertEquals(hb0.getNeigborFromDirection(), clPole.getField(21));
   }
   
   public void testStartingPositionForNoGame()
   {
      System.out.println("testStartingPositionForNoGame");
      game.setNoGame();
            
      assertEquals("", game.getBlackPlayerName());
      assertEquals("", game.getWhitePlayerName());
      assertFalse(game.isActive());
      
      // assert all locations are 0
      int[] whiteLoc = game.getLocationOfPlayer(GenericUtils.COLOR_WHITE);
      int[] blackLoc = game.getLocationOfPlayer(GenericUtils.COLOR_BLACK);
      
      for (int i=0; i<4 ; i++)
      {
         assertTrue(whiteLoc[i] == 0);
         assertTrue(blackLoc[i] == 0);
         
         assertTrue(game.getHraciPole().getHomeField(i, GenericUtils.COLOR_WHITE).getColor() == GenericUtils.COLOR_NEUTRAL);
         assertTrue(game.getHraciPole().getHomeField(i, GenericUtils.COLOR_BLACK).getColor() == GenericUtils.COLOR_NEUTRAL);
         assertTrue(game.getHraciPole().getStartField(i, GenericUtils.COLOR_WHITE).getColor() == GenericUtils.COLOR_NEUTRAL);
         assertTrue(game.getHraciPole().getStartField(i, GenericUtils.COLOR_BLACK).getColor() == GenericUtils.COLOR_NEUTRAL);         
      }
      
   }
   
   public void testStartingPositionAfterBeginOfGame()
   {
      System.out.println("testStartingPositionAfterBeginOfGame");
      game.setNewGameState("wpl", "bpl", true);
      
      // test locations      
      int[] whiteLoc = game.getLocationOfPlayer(GenericUtils.COLOR_WHITE);
      int[] blackLoc = game.getLocationOfPlayer(GenericUtils.COLOR_BLACK);  
      
      for (int i=0; i<4 ; i++)
      {
         assertTrue(whiteLoc[i] == 1000 + i);
         assertTrue(blackLoc[i] == 2000 + i);
         
         assertTrue(game.getHraciPole().getHomeField(i, GenericUtils.COLOR_WHITE).getColor() == GenericUtils.COLOR_NEUTRAL);
         assertTrue(game.getHraciPole().getHomeField(i, GenericUtils.COLOR_BLACK).getColor() == GenericUtils.COLOR_NEUTRAL);
         assertTrue(game.getHraciPole().getStartField(i, GenericUtils.COLOR_WHITE).getColor() == GenericUtils.COLOR_WHITE);
         assertTrue(game.getHraciPole().getStartField(i, GenericUtils.COLOR_BLACK).getColor() == GenericUtils.COLOR_BLACK);         
      }
      
      // first turn of white player unsuccessful
      assertTrue(game.isPlayerStillOnGameAfterPlayingWithCube(GenericUtils.COLOR_WHITE, 3));
      assertTrue(game.isPlayerStillOnGameAfterPlayingWithCube(GenericUtils.COLOR_WHITE, 2));
      assertFalse(game.isPlayerStillOnGameAfterPlayingWithCube(GenericUtils.COLOR_WHITE, 5));
      
      // first turn of black player successful after 3 attempts
      assertTrue(game.isPlayerStillOnGameAfterPlayingWithCube(GenericUtils.COLOR_BLACK, 3));
      assertTrue(game.isPlayerStillOnGameAfterPlayingWithCube(GenericUtils.COLOR_BLACK, 4));
      assertTrue(game.isPlayerStillOnGameAfterPlayingWithCube(GenericUtils.COLOR_BLACK, 6));
      
      Collection<CloveceField> clf = game.getAllFigurkasWhichCanPlay(GenericUtils.COLOR_BLACK, 6);
      assertTrue(clf.size() == 4);
      
      // now we have field from start field of white player
      CloveceField startField = clf.iterator().next();
      
      // decide were we can play
      Collection<CloveceField> fg = game.getHraciPole().getFieldsWhereFigurkaCanPlay(startField, 6, GenericUtils.COLOR_BLACK);
      assertTrue(fg.size() == 1);
      CloveceField fieldTo = fg.iterator().next();
      
      // make sure that field is empty before playing
      assertTrue(game.getHraciPole().getFieldById(20).getColor() == GenericUtils.COLOR_NEUTRAL);
      
      // play now
      int st = game.handlePlayingWithFigurkas(6, startField, fieldTo);
      
      // assert correct state
      assertTrue(st == 1);
      int[] loc = game.getLocationOfPlayer(GenericUtils.COLOR_BLACK);
      List<?> list = Arrays.asList(loc[0], loc[1], loc[2], loc[3]);
      assertTrue(list.size() == 4);
      assertTrue(list.contains(20));
      assertTrue(game.getHraciPole().getFieldById(20).getColor() == GenericUtils.COLOR_BLACK);            
   }
   
   /**
    * Here we test that moving out is possible but moving out of our own figurka is not possible.    
    */
   public void testMovingOut()
   {
      System.out.println("testMovingOut");
      game.setNewGameState("wpl", "bpl", false);
      int[] wloc = {1000, 1001, 38, 35};
      int[] blloc = {2000, 2001, 2002, 32};
      
      game.setLocationOfPlayer(GenericUtils.COLOR_WHITE, wloc);
      game.setLocationOfPlayer(GenericUtils.COLOR_BLACK, blloc);
      
      // assert that we can't move out our figurka but we can move out opponent figurka
      Collection<CloveceField> fieldsForPlay = game.getAllFigurkasWhichCanPlay(GenericUtils.COLOR_WHITE, 3);
      assertTrue(fieldsForPlay.size() == 1);
      CloveceField fieldFrom = fieldsForPlay.iterator().next();
      assertTrue(fieldFrom.equals(game.getHraciPole().getFieldById(35)));
      
      // assert that we can play from 35 to 32
      Collection<CloveceField> fieldsTo = game.getHraciPole().getFieldsWhereFigurkaCanPlay(fieldFrom, 3, GenericUtils.COLOR_WHITE);
      assertTrue(fieldsTo.size() == 1);
      CloveceField fieldTo = fieldsTo.iterator().next();
      assertEquals(fieldTo, game.getHraciPole().getFieldById(32));
      
      // play and move out figurka of black player
      game.handlePlayingWithFigurkas(3, fieldFrom, fieldTo);
      
      // assert that all black figurkas are at home now
      int[] loc = game.getLocationOfPlayer(GenericUtils.COLOR_BLACK);
      List<?> list = Arrays.asList(loc[0], loc[1], loc[2], loc[3]);
      assertTrue(list.contains(2000));
      assertTrue(list.contains(2001));
      assertTrue(list.contains(2002));
      assertTrue(list.contains(2003));
      
      game.setWhiteNaTahu(false);
      
      // assert that black player have 3 attempts because he has all figurkas at home now
      assertTrue(game.isPlayerStillOnGameAfterPlayingWithCube(GenericUtils.COLOR_BLACK, 3));
      assertTrue(game.isPlayerStillOnGameAfterPlayingWithCube(GenericUtils.COLOR_BLACK, 4));
      assertFalse(game.isPlayerStillOnGameAfterPlayingWithCube(GenericUtils.COLOR_BLACK, 2));      
      
   }
   
   /**
    * Here we test that we can go only to home field if we have possibility to go to home field
    */
   public void testGoingToHomeField()
   {
      System.out.println("testGoingToHomeField");
      game.setNewGameState("wpl", "bpl", true);
      int[] wloc = {1000, 100, 102, 3};
      int[] blloc = {2000, 2001, 2002, 2003};
      
      game.setLocationOfPlayer(GenericUtils.COLOR_WHITE, wloc);
      game.setLocationOfPlayer(GenericUtils.COLOR_BLACK, blloc);   
      
      // assert that we can move only with figurka 100 when we have 3 on dice
      Collection<CloveceField> fieldsForPlay = game.getAllFigurkasWhichCanPlay(GenericUtils.COLOR_WHITE, 3);
      assertTrue(fieldsForPlay.size() == 1);
      CloveceField fieldFrom = fieldsForPlay.iterator().next();
      assertTrue(fieldFrom.equals(game.getHraciPole().getFieldById(100)));      
      
      // assert that we can play from 100 to 103 when we have 3 on dice
      Collection<CloveceField> fieldsTo = game.getHraciPole().getFieldsWhereFigurkaCanPlay(fieldFrom, 3, GenericUtils.COLOR_WHITE);
      assertTrue(fieldsTo.size() == 1);
      CloveceField fieldTo = fieldsTo.iterator().next();
      assertEquals(fieldTo, game.getHraciPole().getFieldById(103));      
      
      // assert that we can move only with figurka 3 when we have 4 on dice
      fieldsForPlay = game.getAllFigurkasWhichCanPlay(GenericUtils.COLOR_WHITE, 4);
      assertTrue(fieldsForPlay.size() == 1);
      fieldFrom = fieldsForPlay.iterator().next();
      assertTrue(fieldFrom.equals(game.getHraciPole().getFieldById(3)));      
      
      // assert that we can play from 3 to 101 when we have 4 on dice
      fieldsTo = game.getHraciPole().getFieldsWhereFigurkaCanPlay(fieldFrom, 4, GenericUtils.COLOR_WHITE);
      assertTrue(fieldsTo.size() == 1);
      fieldTo = fieldsTo.iterator().next();
      assertEquals(fieldTo, game.getHraciPole().getFieldById(101));        
   }
   
   /**
    * dom some test for ending of game.
    */
   public void testEndOfGame()
   {
      System.out.println("testEndOfGame");
      game.setNewGameState("wpl", "bpl", true);
      int[] wloc = {100, 101, 102, 2};
      int[] blloc = {2000, 2001, 2002, 2003};
      
      game.setLocationOfPlayer(GenericUtils.COLOR_WHITE, wloc);
      game.setLocationOfPlayer(GenericUtils.COLOR_BLACK, blloc);         
      
      // We can't go nowhere when we have 6 on dice but we should play again
      assertTrue(game.isPlayerStillOnGameAfterPlayingWithCube(GenericUtils.COLOR_WHITE, 6));
      
      // assert that we can move only with figurka 2 when we have 5 on dice
      Collection<CloveceField> fieldsForPlay = game.getAllFigurkasWhichCanPlay(GenericUtils.COLOR_WHITE, 5);
      assertTrue(fieldsForPlay.size() == 1);
      CloveceField fieldFrom = fieldsForPlay.iterator().next();
      assertTrue(fieldFrom.equals(game.getHraciPole().getFieldById(2)));        
      
      // assert that we can move with figurka 2 and with figurka 102 when we have 1 on dice
      fieldsForPlay = game.getAllFigurkasWhichCanPlay(GenericUtils.COLOR_WHITE, 1);
      assertTrue(fieldsForPlay.size() == 2);
      assertTrue(fieldsForPlay.contains(game.getHraciPole().getFieldById(2)));
      assertTrue(fieldsForPlay.contains(game.getHraciPole().getFieldById(102)));
      fieldFrom = game.getHraciPole().getFieldById(2);
      
      // move by 1 with field 2 and assert that opponent can play after it
      int st = game.handlePlayingWithFigurkas(1, fieldFrom, game.getHraciPole().getFieldById(1));
      assertTrue(st == 0);
      
      // Play by opponent
      assertTrue(game.isPlayerStillOnGameAfterPlayingWithCube(GenericUtils.COLOR_BLACK, 3));
      assertTrue(game.isPlayerStillOnGameAfterPlayingWithCube(GenericUtils.COLOR_BLACK, 4));
      assertFalse(game.isPlayerStillOnGameAfterPlayingWithCube(GenericUtils.COLOR_BLACK, 2));   
      
      // assert that only figurka 1 can play if we hav 4 on dice      
      fieldsForPlay = game.getAllFigurkasWhichCanPlay(GenericUtils.COLOR_WHITE, 4);
      assertTrue(fieldsForPlay.size() == 1);
      assertTrue(fieldsForPlay.contains(game.getHraciPole().getFieldById(1)));      
      fieldFrom = game.getHraciPole().getFieldById(1);
      
      // play now and check that game is finished
      st = game.handlePlayingWithFigurkas(4, fieldFrom, game.getHraciPole().getFieldById(103));
      assertTrue(st == 2);
      
   }

}

